package com.njuse.seecjvm.instructions.references;

import com.njuse.seecjvm.instructions.base.Index16Instruction;
import com.njuse.seecjvm.memory.jclass.Field;
import com.njuse.seecjvm.memory.jclass.InitState;
import com.njuse.seecjvm.memory.jclass.JClass;
import com.njuse.seecjvm.memory.jclass.runtimeConstantPool.RuntimeConstantPool;
import com.njuse.seecjvm.memory.jclass.runtimeConstantPool.constant.ref.FieldRef;
import com.njuse.seecjvm.runtime.OperandStack;
import com.njuse.seecjvm.runtime.StackFrame;
import com.njuse.seecjvm.runtime.Vars;
import com.njuse.seecjvm.runtime.struct.JObject;


public class PUTFIELD extends Index16Instruction {
    /**
     * TODO 实现这条指令
     * 其中 对应的index已经读取好了
     */
    @Override
    public void execute(StackFrame frame) {
    	
    	RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool();
    	FieldRef t=(FieldRef) runtimeConstantPool.getConstant(index);
    	Field field;
    	 try {
             field = t.getResolvedFieldRef();
             String descriptor = field.getDescriptor();
             OperandStack stack = frame.getOperandStack();
             int slotID = field.getSlotID();
             /*
             JClass targetClazz = field.getClazz();
             if (targetClazz.getInitState() == InitState.PREPARED) {
                 frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                 targetClazz.initClass(frame.getThread(), targetClazz);
                 return;
             }


             */
             switch (descriptor.charAt(0)) {
                 case 'Z':
                 case 'B':
                 case 'C':
                 case 'S':
                 case 'I':
                	 int tempint=stack.popInt();
                	 JObject tint=stack.popObjectRef();
                     JClass targetClazzint = tint.getClazz();
                     if (targetClazzint.getInitState() == InitState.PREPARED) {
                         frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                         targetClazzint.initClass(frame.getThread(), targetClazzint);
                         return;
                     }
                     Vars staticVarsint = targetClazzint.getStaticVars();
                     staticVarsint.setInt(slotID, tempint);
                     break;
                 case 'F':
                	 float tempfloat=stack.popFloat();
                	 JObject tfloat=stack.popObjectRef();
                     JClass targetClazzfloat = tfloat.getClazz();
                     if (targetClazzfloat.getInitState() == InitState.PREPARED) {
                         frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                         targetClazzfloat.initClass(frame.getThread(), targetClazzfloat);
                         return;
                     }
                     Vars staticVarsfloat = targetClazzfloat.getStaticVars();
                     staticVarsfloat.setFloat(slotID, tempfloat);
                     break;
                 case 'J':
                	 long templong=stack.popLong();
                	 JObject tlong=stack.popObjectRef();
                     JClass targetClazzlong = tlong.getClazz();
                     if (targetClazzlong.getInitState() == InitState.PREPARED) {
                         frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                         targetClazzlong.initClass(frame.getThread(), targetClazzlong);
                         return;
                     }
                     Vars staticVarslong = targetClazzlong.getStaticVars();
                     staticVarslong.setLong(slotID, templong);
                     break;
                 case 'D':
                	 double tempdouble=stack.popDouble();
                	 JObject tdouble=stack.popObjectRef();
                     JClass targetClazzdouble = tdouble.getClazz();
                     if (targetClazzdouble.getInitState() == InitState.PREPARED) {
                         frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                         targetClazzdouble.initClass(frame.getThread(), targetClazzdouble);
                         return;
                     }
                     Vars staticVarsdouble = targetClazzdouble.getStaticVars();
                     staticVarsdouble.setDouble(slotID, tempdouble);
                     break;
                 case 'L':
                 case '[':
                	 JObject tempobject=stack.popObjectRef();
                	 JObject tobject=stack.popObjectRef();
                     JClass targetClazzobject = tobject.getClazz();
                     if (targetClazzobject.getInitState() == InitState.PREPARED) {
                         frame.setNextPC(frame.getNextPC() - 3);//opcode + operand = 3bytes
                         targetClazzobject.initClass(frame.getThread(), targetClazzobject);
                         return;
                     }
                     Vars staticVarsobject = targetClazzobject.getStaticVars();
                     staticVarsobject.setObjectRef(slotID, tempobject);
                     break;
                 default:
             }
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         }
    }

}
